package com.sgcc.pda.h5.businessHw;

import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.RemoteException;
import android.util.Log;

import com.sgcc.pda.CommonResultsFactory;
import com.sgcc.pda.baselibrary.utils.LogUtil;
import com.sgcc.pda.business.IBusinessHw;
import com.sgcc.pda.business.IBusinessHwCallback;
import com.sgcc.pda.common.aidl.CommonCallback;
import com.sgcc.pda.common.aidl.CommonParams;
import com.sgcc.pda.common.aidl.CommonResults;

import org.json.JSONException;
import org.json.JSONObject;

import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

/**
 * @author superFan
 * date: 2019/10/10/010 11:38
 * Copyright (c) 2019 hezhongweiqi.Co.Ltd. All rights reserved.
 * description: HwBinderUtil 的基础类， 所有的HW的功能都基于此类，使用通用的postToPlugin方法
 * 虽然在jsbridge注册时，稍微麻烦；但也是为了将各个业务的功能区分开
 */
public class BaseBusinessHwBinderUtil {
    private static final String TAG = "BusinessHwBaseBinderUti";
    protected static IBusinessHw mService = null;

    private boolean isBind = false;

    protected BaseBusinessHwBinderUtil() {
    }

    public IBusinessHw getBindService() {
        return mService;
    }

    private static class Instance {
        private static final BaseBusinessHwBinderUtil mInstance = new BaseBusinessHwBinderUtil();
    }

    /**
     * 单例
     */
    public static BaseBusinessHwBinderUtil getInstance() {
        return BaseBusinessHwBinderUtil.Instance.mInstance;
    }

    private ServiceConnection mConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            LogUtil.d(name.getClassName() + "BusinessHw AIDL服务绑定成功");
            mService = IBusinessHw.Stub.asInterface(service);
            isBind = true;
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            LogUtil.d(name.getClassName() + "BusinessHw AIDL服务断开");
            isBind = false;
            mService = null;
        }
    };

    /**
     * 绑定掌机基础服务提供接口的AIDL服务
     *
     * @param context
     * @return 是否绑定
     */
    public boolean bind(Context context) {
        if (isBind) {
            return isBind;
        }
        Intent intent = new Intent("com.sgcc.pda.business.AIDL_BUSINESSHW_SERVICE");
        intent.setPackage("com.sgcc.pda.hw");
        try {
            isBind = context.bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
        } catch (Exception e) {
            LogUtil.e(TAG, "bind: " + e.getMessage());
            isBind = false;
        }
        return isBind;
    }

    /**
     * 取消绑定掌机基础服务提供接口的AIDL服务
     *
     * @param context
     * @return 是否绑定
     */
    public void unbind(Context context) {
        try {
            context.unbindService(mConnection);
        } catch (Exception e) {
            LogUtil.e(TAG, "unbind: " + e.getMessage());
        }
    }

    /**
     * 根据方法名执行对应的方法
     *
     * @param params   参数
     * @param callback 回调
     * @return 结果
     */
    public CommonResults execute(CommonParams params, CommonCallback callback) {
        String methodName = params.getMethodName();
        CommonResults commonResults = CommonResultsFactory.successResults();
        try {
            // 通过反射调用方法，方法参数与返回值必须统一成（CommonParams，CommonCallback，CommonResults）
            Method method = getClass().getMethod(methodName, CommonParams.class, CommonCallback.class);
            commonResults = (CommonResults) method.invoke(this, params, callback);
        } catch (Exception e) {
            e.printStackTrace();
            commonResults = CommonResultsFactory.methodInvokeExceptionResults();
            if (callback!=null){
                callback.callback(commonResults);
            }

        }
        Log.d(TAG, "发送请求：" + params.toJSON() + "\n"
                + "返回结果：" + (commonResults == null ? "无" : commonResults.toString()));
        return commonResults;
    }

    /**
     * 通用的调用businessHw 方法
     *
     * @param funcName
     * @param params
     * @param callback
     * @return
     * @throws RemoteException
     */
    public CommonResults postToPlugin(final String funcName, CommonParams params, final CommonCallback callback) {
        CommonResults commonResults = CommonResultsFactory.successResults();
        JSONObject jsonObject = new JSONObject();
        try {
            jsonObject.put("funcName", funcName);
            if (params != null) {
                jsonObject.put("params", new JSONObject(params.getParams()));
            }
        } catch (JSONException e) {
            e.printStackTrace();
            commonResults = CommonResultsFactory.parametersExceptionResults();
            if (callback != null){
                callback.callback(commonResults);
            }
            return commonResults;
        }
        final CommonResults finalCommonResults = commonResults;
        if (getBindService() != null) {
            LogUtil.d(TAG, funcName + "执行: " + jsonObject.toString());
            try {
                getBindService().post(jsonObject.toString(), new IBusinessHwCallback.Stub() {
                    @Override
                    public void onCallback(final String data) throws RemoteException {
                        new Handler(Looper.getMainLooper()).post(new Runnable() {
                            @Override
                            public void run() {
                                LogUtil.d(funcName + "结果：" + data);
                                CommonResults commonResults = CommonResultsFactory.successResults();
                                Map<String, Object> map = new HashMap<>();
                                try {
                                    JSONObject jsonObject = new JSONObject(data);
                                    Iterator<String> keys = jsonObject.keys();
                                    for (Iterator<String> it = keys; it.hasNext(); ) {
                                        String key = it.next();
                                        map.put(key, jsonObject.get(key));
                                    }
                                } catch (JSONException e) {
                                    e.printStackTrace();
                                }
                                commonResults.setResults(map);
                                if (callback != null) {
                                    callback.callback(commonResults);
                                }
                            }
                        });
                    }
                });
            } catch (RemoteException e) {
                e.printStackTrace();
                if (callback != null){
                    callback.callback(CommonResultsFactory.remoteExceptionResults());
                }

            }
        } else {
            commonResults = CommonResultsFactory.serviceExceptionResults();
            if (callback != null){
                callback.callback(commonResults);
            }
        }
        return finalCommonResults;
    }

}
